Análisis Exploratorio

data <- fread('HomeSalesData.csv', encoding = 'UTF-8')

La descripción de las variables es la siguiente:

id: identificador para cada casa. date: fecha de venta de la casa. price: precio de venta de la casa. bedrooms: número de habitaciones. bathrooms: número de baños. sqft_living: pies cuadrados del interior de una casa. sqft_lot: pies cuadrados de terreno de una casa. floors: número de plantas de una casa. waterfront: variable dummy que vale 1 si la casa está enfrente del mar. view: índice de 0 a 4 indicando como de buenas son las vistas. condition: índice de 1 a 5 indicando como de buenas son las condiciones de las casas. grade: índice de 1 a 13 indicando el grado de construcción y diseño de la casa (de 1-3 mala construcción y diseño, 7 nivel medio de construcción y diseño y de 11-13 muy buena construcción y diseño). sqft_above: los pies cuadrados del espacio de la vivienda interior que está por encima del nivel del suelo. sqft_basement: pies cuadrados del sotano de una casa. yr_built: año de construcción de la casa. yr_renovated: año de renovación de la casa. zipcode: código postal de la casa. lat: latitud. long: longitud. sqft_living15: pies cuadrados del interior de las casas de los 15 vecinos más próximos. sqft_lot15: pies cuadrados del terreno de las casas de los 15 vecinos más próximos.

Vamos a hacer un pequeño análisis exploratorio para hacernos una idea de cómo se relacionan las variables de nuestro dataset. Previamente, observamos cómo son cada una de las variables por si tenemos que cambiar su clase.

##        id                 date               price        
##  Min.   :   1000102   Length:21613       Min.   :  75000  
##  1st Qu.:2123049194   Class :character   1st Qu.: 321950  
##  Median :3904930410   Mode  :character   Median : 450000  
##  Mean   :4580301520                      Mean   : 540088  
##  3rd Qu.:7308900445                      3rd Qu.: 645000  
##  Max.   :9900000190                      Max.   :7700000  
##     bedrooms        bathrooms      sqft_living       sqft_lot      
##  Min.   : 0.000   Min.   :0.000   Min.   :  290   Min.   :    520  
##  1st Qu.: 3.000   1st Qu.:1.750   1st Qu.: 1427   1st Qu.:   5040  
##  Median : 3.000   Median :2.250   Median : 1910   Median :   7618  
##  Mean   : 3.371   Mean   :2.115   Mean   : 2080   Mean   :  15107  
##  3rd Qu.: 4.000   3rd Qu.:2.500   3rd Qu.: 2550   3rd Qu.:  10688  
##  Max.   :33.000   Max.   :8.000   Max.   :13540   Max.   :1651359  
##      floors        waterfront            view          condition    
##  Min.   :1.000   Min.   :0.000000   Min.   :0.0000   Min.   :1.000  
##  1st Qu.:1.000   1st Qu.:0.000000   1st Qu.:0.0000   1st Qu.:3.000  
##  Median :1.500   Median :0.000000   Median :0.0000   Median :3.000  
##  Mean   :1.494   Mean   :0.007542   Mean   :0.2343   Mean   :3.409  
##  3rd Qu.:2.000   3rd Qu.:0.000000   3rd Qu.:0.0000   3rd Qu.:4.000  
##  Max.   :3.500   Max.   :1.000000   Max.   :4.0000   Max.   :5.000  
##      grade          sqft_above   sqft_basement       yr_built   
##  Min.   : 1.000   Min.   : 290   Min.   :   0.0   Min.   :1900  
##  1st Qu.: 7.000   1st Qu.:1190   1st Qu.:   0.0   1st Qu.:1951  
##  Median : 7.000   Median :1560   Median :   0.0   Median :1975  
##  Mean   : 7.657   Mean   :1788   Mean   : 291.5   Mean   :1971  
##  3rd Qu.: 8.000   3rd Qu.:2210   3rd Qu.: 560.0   3rd Qu.:1997  
##  Max.   :13.000   Max.   :9410   Max.   :4820.0   Max.   :2015  
##   yr_renovated       zipcode           lat             long       
##  Min.   :   0.0   Min.   :98001   Min.   :47.16   Min.   :-122.5  
##  1st Qu.:   0.0   1st Qu.:98033   1st Qu.:47.47   1st Qu.:-122.3  
##  Median :   0.0   Median :98065   Median :47.57   Median :-122.2  
##  Mean   :  84.4   Mean   :98078   Mean   :47.56   Mean   :-122.2  
##  3rd Qu.:   0.0   3rd Qu.:98118   3rd Qu.:47.68   3rd Qu.:-122.1  
##  Max.   :2015.0   Max.   :98199   Max.   :47.78   Max.   :-121.3  
##  sqft_living15    sqft_lot15    
##  Min.   : 399   Min.   :   651  
##  1st Qu.:1490   1st Qu.:  5100  
##  Median :1840   Median :  7620  
##  Mean   :1987   Mean   : 12768  
##  3rd Qu.:2360   3rd Qu.: 10083  
##  Max.   :6210   Max.   :871200
## Classes 'data.table' and 'data.frame':   21613 obs. of  21 variables:
##  $ id           :integer64 7129300520 6414100192 5631500400 2487200875 1954400510 7237550310 1321400060 2008000270 ... 
##  $ date         : chr  "20141013T000000" "20141209T000000" "20150225T000000" "20141209T000000" ...
##  $ price        : num  221900 538000 180000 604000 510000 ...
##  $ bedrooms     : int  3 3 2 4 3 4 3 3 3 3 ...
##  $ bathrooms    : num  1 2.25 1 3 2 4.5 2.25 1.5 1 2.5 ...
##  $ sqft_living  : int  1180 2570 770 1960 1680 5420 1715 1060 1780 1890 ...
##  $ sqft_lot     : int  5650 7242 10000 5000 8080 101930 6819 9711 7470 6560 ...
##  $ floors       : num  1 2 1 1 1 1 2 1 1 2 ...
##  $ waterfront   : int  0 0 0 0 0 0 0 0 0 0 ...
##  $ view         : int  0 0 0 0 0 0 0 0 0 0 ...
##  $ condition    : int  3 3 3 5 3 3 3 3 3 3 ...
##  $ grade        : int  7 7 6 7 8 11 7 7 7 7 ...
##  $ sqft_above   : int  1180 2170 770 1050 1680 3890 1715 1060 1050 1890 ...
##  $ sqft_basement: int  0 400 0 910 0 1530 0 0 730 0 ...
##  $ yr_built     : int  1955 1951 1933 1965 1987 2001 1995 1963 1960 2003 ...
##  $ yr_renovated : int  0 1991 0 0 0 0 0 0 0 0 ...
##  $ zipcode      : int  98178 98125 98028 98136 98074 98053 98003 98198 98146 98038 ...
##  $ lat          : num  47.5 47.7 47.7 47.5 47.6 ...
##  $ long         : num  -122 -122 -122 -122 -122 ...
##  $ sqft_living15: int  1340 1690 2720 1360 1800 4760 2238 1650 1780 2390 ...
##  $ sqft_lot15   : int  5650 7639 8062 5000 7503 101930 6819 9711 8113 7570 ...
##  - attr(*, ".internal.selfref")=<externalptr>
data$yr_renovated <- as.factor(ifelse(is.na(data$yr_renovated), "", ifelse(data$yr_renovated== 0, 0, ifelse(data$yr_renovated < 1995, 1, 2))))


data$yr_built <- as.factor(ifelse(is.na(data$yr_built), "", ifelse(data$yr_built <= 1985, 0, ifelse(data$yr_built > 1985 & data$yr_built < 2010, 1, 2))))


#data$yr_renovated[is.na(data$yr_renovated)] <- "Ausente"

#data$yr_renovated <- as.factor(data$yr_renovated)

Hacemos algunas transformaciones a los datos para sacar variables categóricas de los mismos, que nos den algo más de información sobre el target.

En primer lugar vamos a limpiar la fecha y a ponerle una codificación buena:

clean_date <- function(df = data){
  
  df$date <- gsub('T.*', "", df$date)
  
  df$date <- as.Date(df$date, '%Y%m%d')
  
  return(df)
  
}

df <- clean_date()
current_date <- Sys.Date()

df$antig <- current_date - df$date

Vamos a graficar todas las variables contra el precio de la casa, aunque antes partiremos los datos y todo este análisis lo haremos con los datos de train. Además, hacemos algunas transformaciones y le añadimos algunos datos más al modelo.

df$id <- NULL

df$month <- lubridate::month(df$date)

df$year <- lubridate::year(df$date)

df$price <- log(df$price)

df$zipcode <- NULL

df$date <- NULL

df$latlong <- df$lat * df$long

df$long2 <- df$long**2

df$lat2 <- df$lat**2

df$sqft_living15 <- log1p(df$sqft_living15)

df$sqft_lot15 <- log1p(df$sqft_lot15)

df$sqft_living <- log1p(df$sqft_living)

df$sqft_lot <- log1p(df$sqft_lot)

df$sqft_basement <- log1p(df$sqft_basement)
df$antig <- as.numeric(df$antig)

df$sqft_above <- log1p(df$sqft_above)
df$waterfront <- as.factor(df$waterfront)

df$view <- as.factor(df$view)

df$condition <- as.factor(df$condition)

df$month <- as.factor(df$month)

df$year <- as.factor(df$year)
library(magrittr)
## 
## Attaching package: 'magrittr'
## The following object is masked from 'package:tidyr':
## 
##     extract
## The following object is masked from 'package:ggmap':
## 
##     inset
df$floors <- as.factor(df$floors)

#df$bedrooms <- as.factor(df$bedrooms)

df <- data.frame(df)
X = df[,colnames(df)!="price" & sapply(df, is.numeric)] %<>% scale()

X <- cbind(X, df[, sapply(df, is.factor)])

y <- df$price

total_df <- cbind(X, y)
index_train <- createDataPartition(y, p = 0.8, list = FALSE)  
train <- total_df[index_train,]
test <- total_df[-index_train,]
nrow(train)
## [1] 17292
nrow(test)
## [1] 4321

Bien, como vemos, tenemos 17292 observaciones para entrenar y 4321 para testear nuestros resultados. Ahora vamos a hacer algunas visualizaciones para tratar de encontrar relaciones previas en los datos antes de comenzar a modelizar.

Visualización de los Datos

Vemos una relación lineal clarísima entre la variable sqft_living y price, no tanto entre el año y el precio, por lo que esperamos que esta variable sea menos explicativa. Respecto a la antiguedad, quizás hay demasiados datos para poder dilucir bien cuál es el efecto marginal de esta variable sobre el price.

En primer lugar vemos que existe una relación más o menos clara entre las variables price y sqft_lot; también vemos que sqft_lot está relacionado con sqft_above y sqft_basement, relaciones que vemos a partir del tamaño de los puntos y del color de los mismos. Además, podemos observar en el gráfico de arriba una cosa muy interesante, y es que las casas que tienen más metros cuadrados enla parte de arriba tienen un precio muy superior al resto de las casas; además estas suelen tener metros cuadrados en el basement. Aquí encontramos varias relaciones que pueden ser de interés para los modelos.

Entre la variable latlong y el precio (y) parece que claramente hay relación, negativa; esto significa que sí puede ser de utilidad haber incluido este cruce de las variables iniciales lat y long. Vemos además que las casas con mejor “grade” tienen un precio más alto, pues hay una clara división entre los puntos rojos y los verdes, los cuales representan precisamente esto, el grade de la casa en cuestión.

En este gráfico no se aprecian relaciones.

Se observa una relación positiva entre la variable latitud y el precio de las casas; además, podemos ver que las casas con precios más bajos son de la clase 0 principalmente de yr_builr; las observaciones que pertenecen a las clases 1 y 2 de esta variable tienen en general un precio más alto.

Vemos que las casas con un mayor número de baños tienen un precio más alto que las casas con menos baños. No se observa una relación del todo clara entre la longitud de la casa y el precio de la misma.

Apenas hay diferencias entre las casas que tienen y no tienen waterfront; aunque queda claro que las que no tienen waterfront son en general más baratas, las casas de precio más alto tienen la mayoría waterfront. Podemos ver además que existe una clara relación entre sqft_living15 y el precio de las casas. No se observan diferencias tan notables en el sqft_lot15, se podría decir que los que tienen valores más bajos en esta variable tienden a tener un precio medio, de exp(13) aproximadamente; a ambos lados de ese rango entre el 12.5 y el 14 los sqft_lot15 son más grandes.

Modelos Explicativos Para la variable Price

Dedicaremos la mayor parte de nuestro tiempo al desarrollo de modelos predictivos para la variable Price, sin fijarnos tanto en la interpretabilidad de los modelos; sin embargo, dedicamos también un pequeño apartado aquí a los modelos explicativos. Para esta parte probaremos modelos muy sencillos, pues se interpretan bastante mejor. Aprovechamos para comentar aquí que no se observarán en las fórmulas demasiadas transformaciones con variables, esto es porque las variables que debían ser transformadas (al logaritmo por ejemplo), ya fueron transformadas anteriormente; se realizó un análisis previo, que no se enseña en este Markdown, en el que se vio cómo era el efecto de cada variable con la variable objetivo (el precio de las casas) y cómo sería en función de las diferentes transformaciones posibles.

linearM <- lm(y ~., data = train)

summary(linearM)
## 
## Call:
## lm(formula = y ~ ., data = train)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -1.1522 -0.1520 -0.0028  0.1444  1.2008 
## 
## Coefficients:
##                 Estimate Std. Error t value Pr(>|t|)    
## (Intercept)    1.263e+01  7.917e-02 159.464  < 2e-16 ***
## bedrooms      -1.843e-02  2.443e-03  -7.542 4.85e-14 ***
## bathrooms      2.473e-02  3.337e-03   7.411 1.31e-13 ***
## sqft_living    4.651e-02  9.474e-03   4.910 9.21e-07 ***
## sqft_lot       4.763e-02  4.810e-03   9.903  < 2e-16 ***
## grade          1.656e-01  3.276e-03  50.569  < 2e-16 ***
## sqft_above     1.066e-01  9.484e-03  11.242  < 2e-16 ***
## sqft_basement  4.220e-02  4.733e-03   8.914  < 2e-16 ***
## lat            4.307e+00  1.956e+00   2.202 0.027701 *  
## long           3.523e+01  2.323e+00  15.161  < 2e-16 ***
## sqft_living15  7.925e-02  3.117e-03  25.426  < 2e-16 ***
## sqft_lot15    -3.104e-02  4.720e-03  -6.576 4.96e-11 ***
## antig          3.822e-02  2.443e-02   1.564 0.117811    
## latlong       -5.949e+01  1.989e+00 -29.904  < 2e-16 ***
## long2          1.433e+01  2.187e+00   6.555 5.72e-11 ***
## lat2          -5.703e+01  1.269e+00 -44.924  < 2e-16 ***
## floors1.5      7.447e-02  7.187e-03  10.362  < 2e-16 ***
## floors2       -7.929e-04  6.545e-03  -0.121 0.903574    
## floors2.5      1.094e-01  2.154e-02   5.081 3.80e-07 ***
## floors3       -2.226e-02  1.351e-02  -1.647 0.099553 .  
## floors3.5      1.645e-01  9.811e-02   1.676 0.093699 .  
## waterfront1    4.115e-01  2.602e-02  15.817  < 2e-16 ***
## view1          1.566e-01  1.520e-02  10.306  < 2e-16 ***
## view2          1.087e-01  9.159e-03  11.865  < 2e-16 ***
## view3          1.843e-01  1.221e-02  15.093  < 2e-16 ***
## view4          2.519e-01  1.934e-02  13.027  < 2e-16 ***
## condition2     8.973e-02  5.420e-02   1.655 0.097841 .  
## condition3     1.485e-01  5.027e-02   2.953 0.003148 ** 
## condition4     2.458e-01  5.030e-02   4.887 1.03e-06 ***
## condition5     3.308e-01  5.063e-02   6.533 6.63e-11 ***
## yr_built1     -1.242e-02  6.513e-03  -1.907 0.056600 .  
## yr_built2      5.620e-02  1.008e-02   5.573 2.54e-08 ***
## yr_renovated1  7.548e-02  1.437e-02   5.252 1.52e-07 ***
## yr_renovated2  2.016e-01  1.215e-02  16.593  < 2e-16 ***
## month2         3.468e-02  1.313e-02   2.640 0.008297 ** 
## month3         7.175e-02  1.657e-02   4.330 1.50e-05 ***
## month4         1.003e-01  2.190e-02   4.578 4.72e-06 ***
## month5         1.241e-01  2.736e-02   4.537 5.75e-06 ***
## month6         1.477e-01  3.430e-02   4.305 1.68e-05 ***
## month7         1.551e-01  4.022e-02   3.855 0.000116 ***
## month8         1.643e-01  4.639e-02   3.541 0.000399 ***
## month9         1.671e-01  5.264e-02   3.173 0.001509 ** 
## month10        1.812e-01  5.905e-02   3.069 0.002152 ** 
## month11        2.014e-01  6.511e-02   3.092 0.001988 ** 
## month12        2.039e-01  7.122e-02   2.863 0.004197 ** 
## year2015       2.188e-01  7.769e-02   2.817 0.004859 ** 
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 0.2393 on 17246 degrees of freedom
## Multiple R-squared:  0.7938, Adjusted R-squared:  0.7933 
## F-statistic:  1476 on 45 and 17246 DF,  p-value: < 2.2e-16

Como tenemos muchas variables, además de que bastantes de ellas son categóricas, el output es enorme. Empecemos diciendo que las variables que no parecen significativas a la hora de explicar el precio serían (cogemos 0.10 como significance level) la antiguedad de la casa, el nivel de pisos 2, así como el nivel 3.5 (con respecto al nivel 1, que es el ausente en la ecuación), el nivel 2 de condition, el nivel 2 de month ( es decir, que el pertenecer al mes 2 con respecto a pertenecer al mes 1 la oferta, no es significativa la diferencia sobre el precio). EL número de dormitorios está curiosamente inversamente relacionado con el precio, mientras que el número de baños afecta de forma positiva l mismo. Las variables sqft_living, sqft_lot, sqft_above, sqft_basement, sqft_living15, y sqft_lot15, que pasamos anteriormente a logaritmos, y que ya intuíamos que tendrían una relación con el precio por los gráficos que mostramos antes, tienen todas un efecto positivo sobre el precio excepto la última. Grade es una de las variales que mayor efecto tiene sobre el precio, cuando ésta aumenta en una unidad, el precio aumenta un 16%. La latitud y la longitud (especialmente ésta última) son significativas, y ambas se relacionan de forma positiva con el precio. Las interacciones que introdujimos de estas variables (para captar relaciones no lineales de la zona de las casas con el precio) también son todas significativas. El efecto de latlong sobre el precio es negativo, al igual que el de latitud al cuadrado, mientras que el de longitud al cuadrado es positivo. Tener waterfront, frente a no tenerlo, aumenta el precio de la vivienda. Los niveles que inventamos antes para factorizar los años de construcción y de renovación también son significativos. En general cuanto mayor es el nivel de la variable condition, mayor es el precio, con respecto a si fuera condition nivel 1. Algo parecido pasa con el mes del año; para cada nivel (excepto Febrero) el precio esperado de la casa aumenta con respecto a si la casa se vende en Enero. Vemos además que el \(R^2\) del ajuste es de 0.7929, mientras que el ajustado es de 0.7924; esto significa que en teoría explicamos el 79.24% de la varianza de la variable logprice. Además, la pequeña diferencia entre ambos es un indicador de que no tenemos demasiadas variables incluidas en el modelo, lo cual es bueno a la hora de no producir overfitting (y como dijimos antes, para explicar queremos modelos relativamente sencillos sin demasiadas variables, pues cuantas más tengamos y más interacciones existan entre ellas es más difícil dilucir cuál es el posible, atendiendo a la muestra de datos, efecto marginal de cada una de las variables explicativas sobre el logaritmo del precio).

Ahora probaremos a ajustar un lasso, para ver con cuántas variables se queda (qué betas no transforma a 0).

## [1] 0.7571921
##  [1]  0  1  1  2  2  2  3  3  3  3  3  3  4  5  5  5  5  6  6  6  6  7  7
## [24]  8  9  9  9  9  9  9 10 11 11 11 11 12 12 14 15 16 16 16 16 16 16 16
## [47] 17 17 17 17 17 18 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19
## [70] 19 19 19 19 19

Aquí vemos el \(R^2\) que alcanza la ElasticNet al terminar de optimizarse. Como le hemos puesto \(\alpha = 1\), es una penalización Lasso en su totalidad. Vemos que se ajusta un poco peor que el modelo anterior lineal sin penalización que mostrábamos, esto era de esperar pues estamos forzando al modelo a prescindir de algunas de sus variables. Como vemos, el modelo se acaba quedando con 19 variables, en lugar de las 23 que tenía antes. Este podría ser un mejor modelo para explicar en el sentido de que al eliminar alunas de las variables quitamos algo de ruido y podemos entender mejor qué factores, qué aspectos de una casa o de su entorno hacen que su precio sea elevado. Las variables que antes estaba en la frontera de ser o no rechazadas son las que probablemente el modelo haya decidido eliminar.

Modelos Predictivos Para la Variable Price

Forward

## Linear Regression with Forward Selection 
## 
## 17292 samples
##    23 predictor
## 
## Pre-processing: scaled (45), centered (45) 
## Resampling: Cross-Validated (5 fold, repeated 2 times) 
## Summary of sample sizes: 13833, 13834, 13834, 13834, 13833, 13833, ... 
## Resampling results across tuning parameters:
## 
##   nvmax  RMSE       Rsquared   MAE      
##    5     0.2731265  0.7308934  0.2099447
##    6     0.2675477  0.7417907  0.2056570
##    7     0.2647858  0.7470922  0.2048084
##    8     0.2621159  0.7521496  0.2017188
##    9     0.2552926  0.7648459  0.1965838
##   10     0.2525329  0.7699114  0.1945036
##   11     0.2511455  0.7724295  0.1934588
##   12     0.2494679  0.7754614  0.1919740
##   13     0.2483092  0.7775385  0.1909891
##   14     0.2472359  0.7794649  0.1900500
##   15     0.2458978  0.7818341  0.1889754
##   16     0.2449774  0.7834610  0.1882359
##   17     0.2440963  0.7850242  0.1875947
##   18     0.2437998  0.7855436  0.1875351
## 
## RMSE was used to select the optimal model using the smallest value.
## The final value used for the model was nvmax = 18.

##   (Intercept)   sqft_living         grade    sqft_above           lat 
##   13.04688429    0.12840609    0.17392637    0.03460888    4.20789286 
##          long sqft_living15       latlong          lat2     floors1.5 
##   20.64413307    0.07458741  -59.13078483  -56.57403941    0.02188742 
##   waterfront1         view1         view2         view3         view4 
##    0.03855218    0.02094126    0.02574651    0.03212396    0.03259102 
##    condition3    condition5 yr_renovated2      year2015 
##   -0.04265777    0.02395394    0.03247954    0.02373893
##         RMSE     Rsquared          MAE 
## 1.898782e+05 7.570287e-01 1.034859e+05

Como vemos, de momento la predicción no es del todo correcta, pues nos equivocamos de media en casi 19,000$. Aún así, vemos que los valores predichos y los reales no están tan lejos los unos de los otros.

Probamos ahora con un backward selection, metiéndole de nuevo todas las variables.

Backward

## Linear Regression with Backwards Selection 
## 
## 17292 samples
##    23 predictor
## 
## Pre-processing: scaled (45), centered (45) 
## Resampling: Cross-Validated (5 fold, repeated 2 times) 
## Summary of sample sizes: 13833, 13834, 13832, 13834, 13835, 13832, ... 
## Resampling results across tuning parameters:
## 
##   nvmax  RMSE       Rsquared   MAE      
##    5     0.2877149  0.7013867  0.2223621
##    6     0.2708357  0.7353529  0.2061225
##    7     0.2642485  0.7480943  0.2022768
##    8     0.2578213  0.7601973  0.1990380
##    9     0.2545177  0.7663141  0.1962880
##   10     0.2510372  0.7726339  0.1936071
##   11     0.2486378  0.7769653  0.1917033
##   12     0.2473439  0.7792697  0.1907514
##   13     0.2461858  0.7813265  0.1899628
##   14     0.2452963  0.7829065  0.1892086
##   15     0.2441301  0.7849757  0.1882960
##   16     0.2434778  0.7861186  0.1876593
##   17     0.2426045  0.7876464  0.1868338
##   18     0.2424801  0.7878685  0.1869229
## 
## RMSE was used to select the optimal model using the smallest value.
## The final value used for the model was nvmax = 18.

##   (Intercept)      sqft_lot         grade    sqft_above sqft_basement 
##   13.04688429    0.01602891    0.17172144    0.15638782    0.06770638 
##          long sqft_living15       latlong          lat2     floors1.5 
##   22.33683887    0.07454661  -63.97647659  -56.67370690    0.01947767 
##   waterfront1         view1         view2         view3         view4 
##    0.03824735    0.01957848    0.02372018    0.03039553    0.03128652 
##    condition4    condition5 yr_renovated2      year2015 
##    0.04088408    0.04931686    0.03244478    0.02379902
##         RMSE     Rsquared          MAE 
## 1.888981e+05 7.579709e-01 1.034427e+05

Vemos que la predicción ahora mejora ligeramente, sin grandes resultados pero desde luego mejor que los que estábamos obteniendo con forward.

LeapSeq

Vamos a hacer ahora un leapregression; le aumentamos el número de variables máximas a 21:

leap <- train(form, data = train, 
                  method = "leapSeq", 
                  preProc=c('scale', 'center'),
                  tuneGrid = expand.grid(nvmax = 5:21),
                  trControl = control)
leap
## Linear Regression with Stepwise Selection 
## 
## 17292 samples
##    23 predictor
## 
## Pre-processing: scaled (45), centered (45) 
## Resampling: Cross-Validated (5 fold, repeated 2 times) 
## Summary of sample sizes: 13832, 13834, 13835, 13834, 13833, 13834, ... 
## Resampling results across tuning parameters:
## 
##   nvmax  RMSE       Rsquared   MAE      
##    5     0.2708300  0.7353578  0.2059859
##    6     0.2636966  0.7491074  0.2018670
##    7     0.2585844  0.7587221  0.1994317
##    8     0.2535961  0.7679277  0.1955893
##    9     0.2513900  0.7719347  0.1937539
##   10     0.2503990  0.7737342  0.1928616
##   11     0.2494988  0.7753629  0.1919438
##   12     0.2483953  0.7773540  0.1910489
##   13     0.2504559  0.7731727  0.1928323
##   14     0.2495297  0.7749480  0.1918984
##   15     0.2449799  0.7834541  0.1883447
##   16     0.2439116  0.7853413  0.1875522
##   17     0.2429733  0.7869903  0.1870427
##   18     0.2427941  0.7873023  0.1869760
##   19     0.2422696  0.7882188  0.1866531
##   20     0.2468712  0.7798521  0.1897096
##   21     0.2417682  0.7890901  0.1861533
## 
## RMSE was used to select the optimal model using the smallest value.
## The final value used for the model was nvmax = 21.
plot(leap)

# which variables are selected?
coef(leap$finalModel, leap$bestTune$nvmax)
##   (Intercept)      sqft_lot         grade    sqft_above sqft_basement 
##   13.04688429    0.04665416    0.17058244    0.15255669    0.06654217 
##          long sqft_living15    sqft_lot15       latlong         long2 
##   37.51700545    0.08043925   -0.03035628  -63.30096471   15.41805109 
##          lat2     floors1.5   waterfront1         view1         view2 
##  -56.07302902    0.01822778    0.03846261    0.01922551    0.02291932 
##         view3         view4    condition4    condition5     yr_built2 
##    0.02950573    0.03077086    0.04411799    0.05123427    0.01559638 
## yr_renovated2      year2015 
##    0.03341269    0.02394697
test_results$leap<- exp(predict(leap, test))
postResample(pred = test_results$leap,  obs = test_results$price)
##         RMSE     Rsquared          MAE 
## 1.880474e+05 7.607211e-01 1.029118e+05
rmse = sqrt(mean(test_results$leap - test_results$price)^2)


ggplot(test_results, aes(x = leap, y = price)) +
  
  geom_point() +
  
  geom_smooth(method = "lm", se = F) +
  
  geom_text(aes(label =paste("RMSE=", round(rmse, 3)), x = 1e+06, y = 4e+06))

Seguimos mejorando la predicción con respecto a los dos modelos anteriores. Parece que lo óptimo es incluir 21 variables, mejor que 18 como en el caso anterior. Como vemos que al dejar al modelo tener más variables las coge (esto significa que añadiendo más variables mejora el AIC), vamos a dejar de limitarle a tener un número máximo de variables, pues el objetivo aquí es predecir bien.

Lo siguiente que probaremos será una Ridge Regression; es decir, una regresión múltiple que cuenta con un término adicional que penaliza la inclusión de muchas variables (evitando así el overfitting).

Ridge Regression

## Ridge Regression 
## 
## 17292 samples
##    23 predictor
## 
## Pre-processing: scaled (45), centered (45) 
## Resampling: Cross-Validated (5 fold, repeated 2 times) 
## Summary of sample sizes: 13833, 13834, 13835, 13833, 13833, 13834, ... 
## Resampling results across tuning parameters:
## 
##   lambda       RMSE       Rsquared   MAE      
##   0.000000000  0.2397383  0.7925854  0.1843796
##   0.005263158  0.2567001  0.7622119  0.1988953
##   0.010526316  0.2567471  0.7621533  0.1989267
##   0.015789474  0.2568002  0.7621008  0.1989684
##   0.021052632  0.2568646  0.7620446  0.1990193
##   0.026315789  0.2569410  0.7619837  0.1990795
##   0.031578947  0.2570295  0.7619181  0.1991481
##   0.036842105  0.2571297  0.7618485  0.1992263
##   0.042105263  0.2572414  0.7617751  0.1993136
##   0.047368421  0.2573645  0.7616986  0.1994100
##   0.052631579  0.2574986  0.7616192  0.1995142
##   0.057894737  0.2576436  0.7615374  0.1996251
##   0.063157895  0.2577993  0.7614533  0.1997451
##   0.068421053  0.2579656  0.7613673  0.1998735
##   0.073684211  0.2581422  0.7612795  0.2000116
##   0.078947368  0.2583291  0.7611901  0.2001593
##   0.084210526  0.2585262  0.7610993  0.2003154
##   0.089473684  0.2587332  0.7610072  0.2004794
##   0.094736842  0.2589502  0.7609139  0.2006510
##   0.100000000  0.2591768  0.7608195  0.2008309
## 
## RMSE was used to select the optimal model using the smallest value.
## The final value used for the model was lambda = 0.

##         RMSE     Rsquared          MAE 
## 1.804914e+05 7.797715e-01 1.012362e+05

Vemos que la regresión Ridge mejora aún más la predicción, bajando ya de los 18000 dólares de media del error a 17634.573. Lo curioso sin embargo es que \(\lambda = 0\), es decir, que lo ideal en teoría, a juzgar por la optimización del modelo Ridge, es no penalizar en absoluto a las \(\beta\).

## [1] 0

Lo siguiente que vamos a hacer es añadir variables; esto lo haremos metiendo en la fórmula algunas interacciones entre variables; haremos esto con una Elastic Net que nos permita quedarnos sólo con algunas betas.

Añadiendo variables: Más interacciones. Elastic Net.

form <- y ~ . + bedrooms:bathrooms + sqft_living:sqft_lot:sqft_above:sqft_lot15:sqft_living15:sqft_basement + grade:latlong + grade:sqft_living

grid = expand.grid(alpha = seq(0, .2, 0.01), lambda = seq(0, .1, 0.01))

elasticnet <- train(form, data = train,
                    method='glmnet',
                    preProc=c('scale','center'),
                    tuneGrid = grid,
                    trControl=control)
## glmnet 
## 
## 17292 samples
##    23 predictor
## 
## Pre-processing: scaled (49), centered (49) 
## Resampling: Cross-Validated (5 fold, repeated 2 times) 
## Summary of sample sizes: 13832, 13833, 13834, 13834, 13835, 13835, ... 
## Resampling results across tuning parameters:
## 
##   alpha  lambda  RMSE       Rsquared   MAE      
##   0.00   0.00    0.2550886  0.7655977  0.1980047
##   0.00   0.01    0.2550886  0.7655977  0.1980047
##   0.00   0.02    0.2550886  0.7655977  0.1980047
##   0.00   0.03    0.2550886  0.7655977  0.1980047
##   0.00   0.04    0.2551629  0.7655172  0.1980825
##   0.00   0.05    0.2554323  0.7652325  0.1983615
##   0.00   0.06    0.2557288  0.7649361  0.1986619
##   0.00   0.07    0.2560512  0.7646273  0.1989828
##   0.00   0.08    0.2563935  0.7643130  0.1993235
##   0.00   0.09    0.2567565  0.7639914  0.1996824
##   0.00   0.10    0.2571368  0.7636662  0.2000550
##   0.01   0.00    0.2545307  0.7662923  0.1973354
##   0.01   0.01    0.2546099  0.7661697  0.1974590
##   0.01   0.02    0.2547808  0.7659443  0.1976844
##   0.01   0.03    0.2550062  0.7656771  0.1979538
##   0.01   0.04    0.2552797  0.7653728  0.1982521
##   0.01   0.05    0.2555892  0.7650491  0.1985756
##   0.01   0.06    0.2559288  0.7647129  0.1989218
##   0.01   0.07    0.2562935  0.7643703  0.1992881
##   0.01   0.08    0.2566835  0.7640181  0.1996725
##   0.01   0.09    0.2570935  0.7636632  0.2000685
##   0.01   0.10    0.2575247  0.7633013  0.2004827
##   0.02   0.00    0.2545112  0.7663232  0.1973195
##   0.02   0.01    0.2546303  0.7661374  0.1974977
##   0.02   0.02    0.2548247  0.7658831  0.1977619
##   0.02   0.03    0.2550932  0.7655584  0.1980823
##   0.02   0.04    0.2554092  0.7652045  0.1984275
##   0.02   0.05    0.2557611  0.7648371  0.1987944
##   0.02   0.06    0.2561452  0.7644599  0.1991820
##   0.02   0.07    0.2565631  0.7640656  0.1995972
##   0.02   0.08    0.2570090  0.7636602  0.2000306
##   0.02   0.09    0.2574798  0.7632473  0.2004808
##   0.02   0.10    0.2579759  0.7628239  0.2009511
##   0.03   0.00    0.2545121  0.7663202  0.1973252
##   0.03   0.01    0.2546482  0.7661097  0.1975337
##   0.03   0.02    0.2548801  0.7658013  0.1978479
##   0.03   0.03    0.2551889  0.7654246  0.1982131
##   0.03   0.04    0.2555481  0.7650205  0.1985995
##   0.03   0.05    0.2559484  0.7646004  0.1990096
##   0.03   0.06    0.2563870  0.7641630  0.1994527
##   0.03   0.07    0.2568535  0.7637263  0.1999179
##   0.03   0.08    0.2573587  0.7632650  0.2004078
##   0.03   0.09    0.2578988  0.7627811  0.2009190
##   0.03   0.10    0.2584550  0.7623090  0.2014449
##   0.04   0.00    0.2545092  0.7663265  0.1973296
##   0.04   0.01    0.2546675  0.7660798  0.1975685
##   0.04   0.02    0.2549423  0.7657072  0.1979368
##   0.04   0.03    0.2552928  0.7652766  0.1983444
##   0.04   0.04    0.2557004  0.7648137  0.1987733
##   0.04   0.05    0.2561461  0.7643464  0.1992343
##   0.04   0.06    0.2566272  0.7638770  0.1997240
##   0.04   0.07    0.2571606  0.7633662  0.2002518
##   0.04   0.08    0.2577408  0.7628186  0.2008101
##   0.04   0.09    0.2583402  0.7622847  0.2013784
##   0.04   0.10    0.2589500  0.7617822  0.2019436
##   0.05   0.00    0.2545177  0.7663088  0.1973398
##   0.05   0.01    0.2546886  0.7660467  0.1976076
##   0.05   0.02    0.2550045  0.7656139  0.1980236
##   0.05   0.03    0.2554049  0.7651154  0.1984732
##   0.05   0.04    0.2558597  0.7645969  0.1989547
##   0.05   0.05    0.2563397  0.7641073  0.1994576
##   0.05   0.06    0.2568896  0.7635561  0.2000148
##   0.05   0.07    0.2575008  0.7629499  0.2006128
##   0.05   0.08    0.2581347  0.7623581  0.2012203
##   0.05   0.09    0.2587833  0.7617952  0.2018206
##   0.05   0.10    0.2594582  0.7612349  0.2024317
##   0.06   0.00    0.2545161  0.7663142  0.1973448
##   0.06   0.01    0.2547148  0.7660047  0.1976500
##   0.06   0.02    0.2550758  0.7655050  0.1981128
##   0.06   0.03    0.2555308  0.7649305  0.1986129
##   0.06   0.04    0.2560071  0.7644071  0.1991266
##   0.06   0.05    0.2565504  0.7638414  0.1996969
##   0.06   0.06    0.2571731  0.7632000  0.2003225
##   0.06   0.07    0.2578457  0.7625299  0.2009758
##   0.06   0.08    0.2585344  0.7618943  0.2016188
##   0.06   0.09    0.2592488  0.7612728  0.2022647
##   0.06   0.10    0.2600084  0.7606199  0.2029403
##   0.07   0.00    0.2545346  0.7662883  0.1973442
##   0.07   0.01    0.2547430  0.7659592  0.1976923
##   0.07   0.02    0.2551510  0.7653894  0.1981990
##   0.07   0.03    0.2556423  0.7647733  0.1987428
##   0.07   0.04    0.2561619  0.7642064  0.1993092
##   0.07   0.05    0.2567763  0.7635503  0.1999490
##   0.07   0.06    0.2574690  0.7628243  0.2006350
##   0.07   0.07    0.2581938  0.7621101  0.2013257
##   0.07   0.08    0.2589424  0.7614243  0.2020059
##   0.07   0.09    0.2597419  0.7607045  0.2027170
##   0.07   0.10    0.2605974  0.7599347  0.2034714
##   0.08   0.00    0.2545358  0.7662831  0.1973539
##   0.08   0.01    0.2547731  0.7659100  0.1977356
##   0.08   0.02    0.2552295  0.7652680  0.1982871
##   0.08   0.03    0.2557473  0.7646304  0.1988671
##   0.08   0.04    0.2563281  0.7639867  0.1995018
##   0.08   0.05    0.2570143  0.7632384  0.2002088
##   0.08   0.06    0.2577708  0.7624406  0.2009444
##   0.08   0.07    0.2585461  0.7616895  0.2016615
##   0.08   0.08    0.2593746  0.7609133  0.2024026
##   0.08   0.09    0.2602737  0.7600687  0.2031942
##   0.08   0.10    0.2612336  0.7591644  0.2040370
##   0.09   0.00    0.2545481  0.7662637  0.1973606
##   0.09   0.01    0.2548028  0.7658617  0.1977770
##   0.09   0.02    0.2553173  0.7651300  0.1983826
##   0.09   0.03    0.2558582  0.7644794  0.1989993
##   0.09   0.04    0.2565029  0.7637524  0.1997000
##   0.09   0.05    0.2572614  0.7629113  0.2004701
##   0.09   0.06    0.2580681  0.7620703  0.2012367
##   0.09   0.07    0.2589131  0.7612469  0.2020002
##   0.09   0.08    0.2598359  0.7603508  0.2028183
##   0.09   0.09    0.2608352  0.7593750  0.2036937
##   0.09   0.10    0.2619062  0.7583215  0.2046301
##   0.10   0.00    0.2545486  0.7662626  0.1973660
##   0.10   0.01    0.2548337  0.7658118  0.1978171
##   0.10   0.02    0.2553997  0.7650018  0.1984775
##   0.10   0.03    0.2559741  0.7643209  0.1991352
##   0.10   0.04    0.2566877  0.7635030  0.1999047
##   0.10   0.05    0.2575135  0.7625775  0.2007265
##   0.10   0.06    0.2583696  0.7616981  0.2015222
##   0.10   0.07    0.2592999  0.7607690  0.2023522
##   0.10   0.08    0.2603212  0.7597442  0.2032480
##   0.10   0.09    0.2614315  0.7586172  0.2042175
##   0.10   0.10    0.2626110  0.7574175  0.2052420
##   0.11   0.00    0.2545614  0.7662428  0.1973732
##   0.11   0.01    0.2548679  0.7657560  0.1978590
##   0.11   0.02    0.2554695  0.7648992  0.1985613
##   0.11   0.03    0.2560945  0.7641556  0.1992769
##   0.11   0.04    0.2568811  0.7632378  0.2001136
##   0.11   0.05    0.2577636  0.7622521  0.2009728
##   0.11   0.06    0.2586826  0.7613077  0.2018114
##   0.11   0.07    0.2597056  0.7602575  0.2027135
##   0.11   0.08    0.2608372  0.7590812  0.2037018
##   0.11   0.09    0.2620617  0.7577962  0.2047708
##   0.11   0.10    0.2633322  0.7564885  0.2058597
##   0.12   0.00    0.2545531  0.7662598  0.1973669
##   0.12   0.01    0.2549048  0.7656955  0.1979030
##   0.12   0.02    0.2555371  0.7648021  0.1986449
##   0.12   0.03    0.2562196  0.7639827  0.1994210
##   0.12   0.04    0.2570792  0.7629659  0.2003208
##   0.12   0.05    0.2580098  0.7619379  0.2012101
##   0.12   0.06    0.2590107  0.7608916  0.2021068
##   0.12   0.07    0.2601377  0.7597006  0.2030957
##   0.12   0.08    0.2613803  0.7583707  0.2041819
##   0.12   0.09    0.2627134  0.7569399  0.2053374
##   0.12   0.10    0.2640469  0.7555797  0.2064583
##   0.13   0.00    0.2545441  0.7662742  0.1973576
##   0.13   0.01    0.2549446  0.7656298  0.1979485
##   0.13   0.02    0.2556048  0.7647058  0.1987285
##   0.13   0.03    0.2563529  0.7637975  0.1995714
##   0.13   0.04    0.2572793  0.7626932  0.2005243
##   0.13   0.05    0.2582614  0.7616162  0.2014454
##   0.13   0.06    0.2593558  0.7604458  0.2024156
##   0.13   0.07    0.2605900  0.7591079  0.2034970
##   0.13   0.08    0.2619452  0.7576197  0.2046782
##   0.13   0.09    0.2633580  0.7560986  0.2058862
##   0.13   0.10    0.2647457  0.7547120  0.2070280
##   0.14   0.00    0.2545393  0.7662810  0.1973621
##   0.14   0.01    0.2549850  0.7655630  0.1979945
##   0.14   0.02    0.2556769  0.7646023  0.1988166
##   0.14   0.03    0.2564877  0.7636072  0.1997218
##   0.14   0.04    0.2574824  0.7624153  0.2007293
##   0.14   0.05    0.2585243  0.7612781  0.2016842
##   0.14   0.06    0.2597173  0.7599741  0.2027399
##   0.14   0.07    0.2610687  0.7584673  0.2039215
##   0.14   0.08    0.2625203  0.7568516  0.2051793
##   0.14   0.09    0.2639795  0.7553134  0.2064028
##   0.14   0.10    0.2654350  0.7538686  0.2075879
##   0.15   0.00    0.2545370  0.7662848  0.1973620
##   0.15   0.01    0.2550255  0.7654964  0.1980400
##   0.15   0.02    0.2557526  0.7644938  0.1989074
##   0.15   0.03    0.2566318  0.7634020  0.1998783
##   0.15   0.04    0.2576770  0.7621580  0.2009173
##   0.15   0.05    0.2587976  0.7609220  0.2019321
##   0.15   0.06    0.2600991  0.7594652  0.2030800
##   0.15   0.07    0.2615614  0.7577980  0.2043558
##   0.15   0.08    0.2631022  0.7560745  0.2056769
##   0.15   0.09    0.2646008  0.7545350  0.2069118
##   0.15   0.10    0.2661239  0.7530340  0.2081553
##   0.16   0.00    0.2545475  0.7662697  0.1973684
##   0.16   0.01    0.2550683  0.7654256  0.1980866
##   0.16   0.02    0.2558303  0.7643815  0.1989988
##   0.16   0.03    0.2567777  0.7631946  0.2000344
##   0.16   0.04    0.2578733  0.7619001  0.2011034
##   0.16   0.05    0.2590840  0.7605440  0.2021910
##   0.16   0.06    0.2604974  0.7589248  0.2034338
##   0.16   0.07    0.2620677  0.7571071  0.2047999
##   0.16   0.08    0.2636582  0.7553558  0.2061415
##   0.16   0.09    0.2652245  0.7537567  0.2074215
##   0.16   0.10    0.2668266  0.7521725  0.2087384
##   0.17   0.00    0.2545455  0.7662731  0.1973598
##   0.17   0.01    0.2551131  0.7653511  0.1981347
##   0.17   0.02    0.2559063  0.7642729  0.1990890
##   0.17   0.03    0.2569281  0.7629794  0.2001932
##   0.17   0.04    0.2580722  0.7616394  0.2012891
##   0.17   0.05    0.2593829  0.7601422  0.2024612
##   0.17   0.06    0.2609120  0.7583530  0.2038026
##   0.17   0.07    0.2625871  0.7563907  0.2052509
##   0.17   0.08    0.2642003  0.7546683  0.2065891
##   0.17   0.09    0.2658406  0.7529969  0.2079332
##   0.17   0.10    0.2675421  0.7512874  0.2093351
##   0.18   0.00    0.2545471  0.7662711  0.1973631
##   0.18   0.01    0.2551583  0.7652762  0.1981832
##   0.18   0.02    0.2559870  0.7641565  0.1991837
##   0.18   0.03    0.2570759  0.7627714  0.2003473
##   0.18   0.04    0.2582792  0.7613644  0.2014797
##   0.18   0.05    0.2596968  0.7597131  0.2027430
##   0.18   0.06    0.2613479  0.7577419  0.2041883
##   0.18   0.07    0.2630675  0.7557576  0.2056570
##   0.18   0.08    0.2647492  0.7539713  0.2070409
##   0.18   0.09    0.2664664  0.7522184  0.2084555
##   0.18   0.10    0.2682628  0.7503926  0.2099325
##   0.19   0.00    0.2545397  0.7662829  0.1973715
##   0.19   0.01    0.2552045  0.7651993  0.1982344
##   0.19   0.02    0.2560703  0.7640353  0.1992792
##   0.19   0.03    0.2572244  0.7625629  0.2005003
##   0.19   0.04    0.2584958  0.7610731  0.2016776
##   0.19   0.05    0.2600236  0.7592600  0.2030337
##   0.19   0.06    0.2617806  0.7571383  0.2045657
##   0.19   0.07    0.2635501  0.7551229  0.2060615
##   0.19   0.08    0.2652916  0.7532912  0.2074926
##   0.19   0.09    0.2671089  0.7514092  0.2089912
##   0.19   0.10    0.2690028  0.7494637  0.2105441
##   0.20   0.00    0.2545403  0.7662830  0.1973744
##   0.20   0.01    0.2552515  0.7651213  0.1982865
##   0.20   0.02    0.2561556  0.7639109  0.1993746
##   0.20   0.03    0.2573702  0.7623611  0.2006456
##   0.20   0.04    0.2587220  0.7607647  0.2018830
##   0.20   0.05    0.2603646  0.7587810  0.2033372
##   0.20   0.06    0.2622212  0.7565215  0.2049476
##   0.20   0.07    0.2640235  0.7545123  0.2064542
##   0.20   0.08    0.2658449  0.7525904  0.2079562
##   0.20   0.09    0.2677517  0.7506010  0.2095247
##   0.20   0.10    0.2697193  0.7485895  0.2111401
## 
## RMSE was used to select the optimal model using the smallest value.
## The final values used for the model were alpha = 0.04 and lambda = 0.

##         RMSE     Rsquared          MAE 
## 1.878140e+05 7.497623e-01 1.108452e+05

Como vemos, el modelo se ajusta algo peor cuando se regulariza en exceso, como vemos en el segundo de los dos gráficos superiores; en él se puede apreciar como claramente cuanto mayor es la proporción de penalización del tipo Norma 1 (valor absoluto) con respecto a la proporción de Norma 2 (cuadrado) peor es el modelo, en el sentido de que tiene un error mayor.

Adicionalmente, probaremos ahora con PCR y con PLS, otros dos métodos que utilizan técnicas de reducción de la dimensión con el objetivo de servir de regularizador.

PCR

##         RMSE     Rsquared          MAE 
## 3.225238e+05 4.555277e-01 1.258178e+05

Como vemos, el resultado es algo mejor que utilizando todas las variables, como vemos por el RMSE en el test, pues este es inferior al que habíamos obtenido antes. Vemos que hay una predicción que se le fue muchísimo de las manos, un claro outlier. Seguramente si elimináramos esa observación (aparte de que el gráfico sería más agradable a la vista) el ajuste sería mucho mejor, y el RMSE bajaría incluso más. Los errores grandes tienen un efecto fuerte sobre el MSE, y al hacer la raíz cuadrada de este algo se pueden disipar esos efectos, pero no del todo. Una métrica como el Median Absolute Error podría ser más informativa en casos en los que tenemos algunos claros outliers, pues es una métrica robusta frente a los mismos.

Probamos ahora con PLS (Partial Least Squares), que diseña los componentes con un poco más de criterio, poniéndolos en orden según el efecto que estos tienen sobre la variable objetivo; esto permite que el modelo capte mucho mejor la información útil (en teoría) que los componentes principales sin más.

PLS

##         RMSE     Rsquared          MAE 
## 1.876621e+05 7.500687e-01 1.108063e+05

Vemos que empeora, en términos de RMSE, los resultados obtenidos por el método PCR. No es lo que esperábamos, desde luego, pero los datos han hablado. Mejora, de todas formas, las predicciones realizadas por Ridge y por los otros métodos de regresión que vimos anteriormente.

Vamos a probar, además de los modelos que hemos probado ya, algunos modelos más avanzados de Machine Learning, para comparar esas predicciones con las obtenidas hasta ahora. Para ello utilizaremos Python y el paquete sklearn, pues es infinitamente más rápido que caret. Importaremos desde R un csv con los resultados de las predicciones de un Random Forest y un XGBoost y finalizaremos el análisis de los modelos predictivos.

Como tenemos la partición de train y test ya hecha, vamos a sacar esto a un csv para leerlo desde Python:

write.csv(train, 'train.csv', row.names = F, col.names = T, fileEncoding = 'utf-8', sep = ',')
## Warning in write.csv(train, "train.csv", row.names = F, col.names = T,
## fileEncoding = "utf-8", : attempt to set 'col.names' ignored
## Warning in write.csv(train, "train.csv", row.names = F, col.names = T,
## fileEncoding = "utf-8", : attempt to set 'sep' ignored
write.csv(test, 'test.csv', row.names = F, col.names = T, fileEncoding = 'utf-8', sep = ',')
## Warning in write.csv(test, "test.csv", row.names = F, col.names = T,
## fileEncoding = "utf-8", : attempt to set 'col.names' ignored
## Warning in write.csv(test, "test.csv", row.names = F, col.names = T,
## fileEncoding = "utf-8", : attempt to set 'sep' ignored

Resultados Finales

rf <- read.csv('preds_rf.txt', fileEncoding = 'utf-8', header = F)

xgb <- read.csv('preds_xgb.txt', fileEncoding = 'utf-8', header = F)
rmse = sqrt(mean(test_results$price - test_results$rf)^2)


ggplot(test_results, aes(x = rf, y = price)) +
  
  geom_point() +
  
  geom_smooth(method = "lm", se = F) +
  
  geom_text(aes(label =paste("RMSE=", round(rmse, 3)), x = 1e+06, y = 4e+06))

Vaya, pues curiosamente el Random Forest predice bastante peor que los modelos lineales que utilizamos anteriormente. Parece tener un pequeño sesgo, predice precios más bajos de lo que suelen ser, especialmente para las casas de mayor valor.

Vamos a visualizar los resultados para XGBoost.

# Let's look again at the performance for all models:
apply(test_results[-1], 2, function(x) cor(x,test_results$price)^2)
##          frw          brw         leap        ridge         enet 
## 7.570287e-01 7.579709e-01 7.607211e-01 7.797715e-01 7.497623e-01 
##          pcr          pls           rf          xgb 
## 4.555277e-01 7.500687e-01 9.358482e-07 1.367145e-05
apply(test_results[-1], 2, function(x) mean(abs(x - test_results$price)))
##      frw      brw     leap    ridge     enet      pcr      pls       rf 
## 103485.9 103442.7 102911.8 101236.2 110845.2 125817.8 110806.3 243260.1 
##      xgb 
## 287480.4

Arriba podemos ver el R^2 y el MAE de todos los modelos que hemos probado. Vemos que el peor es claramente el PCR, mientras que el mejor no está del todo caro, pues la mayoría alcanzan resultados bastante similares. En términos de \(R^2\) parece que el mejor es XGBoost. Random Forest no funciona demasiado bien para este problema, ya que queda muy por debajo de modelos como Ridge o la Elastic Net.

La correlación es bastante alta entre modelos, lo cual es negativo a la hora de juntarlos, debido a que los Ensemble Models se benefician precisamente de la diversidad de los modelos, si todos los modelos tienen errores parecidos con respecto al precio, es difícil que un método de ensemble learning pueda predecir mejor que ellos individualmente teniéndolos a todos en cuenta. Podríamos también simplemente hacer la media de las predicciones y ver cuánto nos reportaría eso de error…

test_results$media <- rowMeans(test_results[, -1])

cor(test_results$media,test_results$price)^2
## [1] 0.7356881

Como vemos, no mejora, de hecho empeora con respecto a utilizar sólo el Ridge por ejemplo.

Ahora vamos a encargarnos de los intervalos de confianza de un modelo simple lineal con todas las variables, para hacer algunas comprobaciones finales.

##         fit      lwr      upr
## 3  322923.1 217722.8 478954.5
## 5  452839.7 305372.7 671519.9
## 7  226140.0 152499.6 335340.6
## 12 399230.7 269240.5 591980.4
## 19 195747.6 131995.6 290290.8
## 20 224986.7 151733.1 333605.8
## [1] 0.09419116

## [1] 278464.7 321203.0 820425.6 286041.0 385201.4 426059.2

Tan sólo el 9.7% de las predicciones no contienen el valor real en su intervalo de confianza. Vemos que las predicciones son bastante asimétricas… Esto podría ser bueno a la hora de combinarlo con otro modelo que tuviera otro tipo de sesgo.

Vamos a probar finalmente a computar los intervalos de confianza de las predicciones de otra forma, mostrando en última instancia el gráfico en el que, según estos cálculos, se aprecian las casas que están realmente dentro del intervalo de predicciones y las que están fuera. Como veremos, este método no paramétrico calcula unos intervalos de confianza para las predicciones más estrechos, por lo que más casas quedarían “mal estimadas”, en comparación con el método anterior, paramétrico.

## [1] 0.3219616

Vemos que en este caso se quedarian fuera el 43% de las casas. Los intervalos calculados de esta forma son mucho más exigentes… Lo que parece que está claro es que los precios de las casas no se distribuyen de forma tan lineal ni al pasarnos a logaritmo, y es que cuanto más subes en la escala de los precios de casa, más alto es el escalón; esto el modelo no lo capta, pues como vemos las predicciones que hace son en general más bajas que el valor real.